<?php

namespace jjl\yii2\db;

use Yii;
use yii\db\ActiveRecord;
use jjl\yii2\db\Helper;
use jjl\yii2\db\ActiveQuery;
use jjl\yii2\db\LogTrait;

abstract class Core extends ActiveRecord {

    public $invalid = false;

    use InitTrait;

    use LogTrait;

    public function init() {
        $this->loadTranslations();
        return parent::init();
    }

    private $update = false;

    public function insert($runValidation = true, $attributes = null) {
        $this->uuid = Helper::uuid();
        return parent::insert($runValidation, $attributes);
    }

    public function update($runValidation = true, $attributeNames = null) {
        if ($this->getDirtyAttributes()) {
            $this->uuid = Helper::uuid(static::tableName());
            $this->update = true;
        }
        return parent::update($runValidation, $attributeNames);
    }

    public function afterSave($insert, $changedAttributes) {
        if ($insert) {
            Yii::$app->dbLog->insert($this);
        } else {
            Yii::$app->dbLog->update($this);
            Yii::$app->dbCache->store('master')->del(static::tableName() . "#{$this->id}");
        }
        parent::afterSave($insert, $changedAttributes);
    }

    public function afterDelete() {
        Yii::$app->dbCache->store('master')->del(static::tableName() . "#{$this->id}");
        Yii::$app->dbLog->delete($this);
        parent::afterDelete();
    }

    public static function find() {
        return Yii::createObject(ActiveQuery::className(), [get_called_class()]);
    }

    static public function findOne($condition) {
        if (is_numeric($condition) || Helper::is_uuid($condition)) {
            if (($value = Yii::$app->dbCache->store('master')->get(static::tableName() . "#{$condition}"))) {
                return self::build($value);
            } else {
                if (is_numeric($condition))
                    $model = parent::findOne($condition);
                else if (Helper::is_uuid($condition))
                    $model = parent::find()->where(['uuid' => $condition])->one();
                if ($model)
                    Yii::$app->dbCache->store('master')->set(static::tableName() . "#{$condition}", $model->getAttributes());
                else if (($dbLog = Yii::$app->dbLog->mapping(static::class)->findOne($condition)))
                    $model = self::build($dbLog->object, true);
                if ($model)
                    return $model;
            }
        } else {
            return parent::findOne($condition);
        }
    }

    /**
     * 
     * @param type $values
     * @param bool $invalid 数据是否失效
     * @return \static
     */
    static public function build($values, bool $invalid = false) {
        $model = new static();
        $model->setAttributes($values, false);
        if ($invalid)
            $model->invalid = true;
        $model->setOldAttributes($values);
        $model->setIsNewRecord(false);
        $model->afterFind();
        return $model;
    }

    /**
     * 获取不带命名空间的类名
     * @return string
     */
    static public function classWithoutNamespace() {
        return ltrim(static::class, __NAMESPACE__);
    }

}
